package com.pxmeta.user.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.pxmeta.common.core.redis.RedisCache;
import com.pxmeta.user.entity.User;
import com.pxmeta.user.entity.dto.UserPositionDTO;
import com.pxmeta.user.entity.vo.NearbyUserVO;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * 附近的人Service
 */
@Service
@Slf4j
public class NearbyUserService {

    @Autowired
    private  RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private RedisCache redisCache;

    public static final String POSITION_KEY = "user_position";

    public static void main(String[] args) {
        String addressByJWD = getAddressByJWD("116.3039", "39.97646");
        JSONObject jsonObject = JSONObject.parseObject(addressByJWD);
        System.out.println(jsonObject);
    }

    /**
     *根据经纬度获取省市区
     */
    public static String getAddressByJWD(String clog, String clat){
        //lat 小  log  大
        //参数解释: 纬度,经度 采用高德API可参考高德文档https://lbs.amap.com/
        //注意key是在高德开放平台申请的key,具体获得key的步骤请查看网址:https://developer.amap.com/api/webservice/guide/create-project/get-key
        String key = "1628ec71ed8e5a0e0151677d901af97e";
        String parameters="?key="+key;
        parameters+="&location="+clog+","+clat;//经纬度坐标
        parameters+="&extensions=all";//返回结果控制，extensions 参数取值为 all 时会返回基本地址信息、附近 POI 内容、道路信息以及道路交叉口信息。
        parameters+="&batch=false";//批量查询控制，batch 参数设置为 false 时进行单点查询，此时即使传入多个经纬度也只返回第一个经纬度的地址解析查询结果。
        parameters+="&roadlevel=0";//道路等级，当 roadlevel = 0 时，显示所有道路
        parameters+="&output=JSON";
        //parameters+="&radius=300";//搜索半径，radius取值范围在0~3000，默认是1000。单位：米
        String urlString = "https://restapi.amap.com/v3/geocode/regeo"+parameters;
        StringBuilder res = new StringBuilder();
        try {
            log.info("高德地图请求地址："+urlString);
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                res.append(line);
            }
            in.close();
            //解析结果
            log.info("高德返回结果：" + res);
            //com.alibaba.fastjson.JSONObject jsonObject1 = jsonObject.getJSONObject("regeocode");
            //res = new StringBuilder(jsonObject1.getString("formatted_address"));
        } catch (Exception e) {
            log.info("获取地址信息异常");
            e.printStackTrace();
            return null;
        }
        return res.toString();
    }
    /**
     * 保存用户地理位置
     * @param userId
     * @param longitude
     * @param latitude
     */
    public String save(String userId, Double longitude, Double latitude){
        String add = null;

        //保存地理位置接口一天只調用一次。

        Boolean obj = redisCache.getCacheObject("savePosition_user_id" + userId);

        if (obj != null){
            return null;
        }
        redisCache.setCacheObject("savePosition_user_id" + userId,Boolean.TRUE,1, TimeUnit.DAYS);

        if (null != longitude && null!=latitude){
//             add = getAddressByJWD(longitude.toString(),latitude.toString());
        }



        redisTemplate.opsForGeo().add(POSITION_KEY, new RedisGeoCommands.GeoLocation<>(userId, new Point(longitude, latitude)));
        return add;
    }


    public List<NearbyUserVO> nearBySearch(double distance, double userLng, double userLat){
        GeoResults<RedisGeoCommands.GeoLocation<Object>> result = redisTemplate.opsForGeo().radius(POSITION_KEY, new Circle(new Point(userLng, userLat), new Distance(distance, Metrics.KILOMETERS)),
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending());

        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = result.getContent();

        List<NearbyUserVO> users = Lists.newLinkedList();

        content.forEach(c->{
            NearbyUserVO vo = new NearbyUserVO();
            vo.setUserId(Long.parseLong(c.getContent().getName().toString()));
            double value = c.getDistance().getValue();
            vo.setDistance(BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP).doubleValue());
            users.add(vo);
        });

        return users;
    }









}
